package com.wzw.springboot.principle.use.datasource;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import java.util.Locale;
import java.util.Objects;

/**
 * @author Wangzhiwen
 */
@Aspect
@Component
public class DynamicDatasourceAspect implements Ordered {

    private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDatasourceAspect.class);

    /**
     * within 意思是自定义注解标注的类下所有的方法都会进入切面的方法
     * annotation 意思是自定义注解标注的方法会进入切面
     */
    @Pointcut("@within(com.wzw.springboot.principle.use.datasource.DatasourceSwitcher)")
    public void datasourceSwitcher() {
    }

    @Around(value = "datasourceSwitcher()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        DatasourceSwitcher annotation = getDatasourceSwitcher(joinPoint);
        try {
            if (Objects.nonNull(annotation)) {
                DynamicDataSourceContextHolder.push(annotation.value().name().toLowerCase(Locale.ROOT));
            }
            return joinPoint.proceed();
        } finally {
            DynamicDataSourceContextHolder.poll();
        }
    }

    private DatasourceSwitcher getDatasourceSwitcher(ProceedingJoinPoint joinPoint) {
        try {
            Class<?> targetClass = joinPoint.getTarget().getClass();
            // 方法上有注解时优先使用
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            if (methodSignature.getMethod().isAnnotationPresent(DatasourceSwitcher.class)) {
                return methodSignature.getMethod().getAnnotation(DatasourceSwitcher.class);
            }
            if (targetClass.isAnnotationPresent(DatasourceSwitcher.class)) {
                return targetClass.getAnnotation(DatasourceSwitcher.class);
            }
            return null;
        } catch (Exception e) {
            LOGGER.error("parse datasourceSwitcher annotation error", e);
            return null;
        }

    }

    /**
     * 切面顺序，控制在事务切面之前
     */
    @Override
    public int getOrder() {
        return Integer.MAX_VALUE - 1;
    }
}
